package com.ljj.examisto.ui.activity

import android.annotation.SuppressLint
import android.app.DatePickerDialog
import android.app.TimePickerDialog
import android.content.SharedPreferences
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.ljj.examisto.R
import com.ljj.examisto.data.item.RemindType
import com.ljj.examisto.data.item.Reminder
import com.ljj.examisto.databinding.ActivityAddExamBinding
import com.ljj.examisto.ui.activity.HomeActivity.Companion.backHome
import com.ljj.examisto.ui.dialog.AddRemindDialog
import com.ljj.examisto.util.DatabaseHelper
import com.ljj.examisto.util.Logger.TAG
import com.ljj.examisto.util.RemindOptionProvider
import com.ljj.examisto.util.RemindOptionProvider.remindOptions
import com.ljj.examisto.ui.dialog.ScrollingTimePickerDialog
import com.ljj.examisto.util.ToastManager
import java.util.Calendar
import kotlin.properties.Delegates

class AddExamActivity : AppCompatActivity(), AddRemindDialog.OnConfirmListener {
    private lateinit var binding: ActivityAddExamBinding
    private lateinit var dbHelper: DatabaseHelper
    private lateinit var prefs: SharedPreferences

    private var examName: String = ""
    private var location: String = ""
    private var is24HourFormat by Delegates.notNull<Boolean>()
    private var selectedYear: Int = 0
    private var selectedMonth: Int = 0
    private var selectedDay: Int = 0
    private var selectedHour: Int = 0
    private var selectedMinute: Int = 0
    private var startTime: Long =  0
    private var duration: Int = 0
    private var remark: String = ""
    private var reminders: MutableList<Reminder> = mutableListOf()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initProperty()
        setupViews()
    }

    override fun onRemindConfirmed(reminder: Reminder) {
        reminders.add(reminder)
        updateRemindersDisplay()
    }

    /* 流程函数 */
    private fun initProperty() {
        binding = ActivityAddExamBinding.inflate(layoutInflater)
        dbHelper = DatabaseHelper.getInstance(this)
        prefs = getSharedPreferences(getString(R.string.app_preference_name), MODE_PRIVATE)
        is24HourFormat = prefs.getBoolean(getString(R.string.key_is_24_hour_format), true)
        initDateTime()
    }

    private fun initDateTime() {
        val calendar = Calendar.getInstance()
        selectedYear = calendar.get(Calendar.YEAR)
        selectedMonth = calendar.get(Calendar.MONTH)
        selectedDay = calendar.get(Calendar.DAY_OF_MONTH)
        selectedHour = calendar.get(Calendar.HOUR_OF_DAY)
        selectedMinute = calendar.get(Calendar.MINUTE)
    }

    private fun setupViews() {
        setContentView(binding.root)
        updateDateDisplay()
        updateTimeDisplay()
        setupBackButton()
        setupSaveButton()
        setupTimeFormatSwitch()
        setupDateButton()
        setupTimeButton()
        setupDurationButton()
        setupAddReminderButton()
    }

    /* 工具函数 */
    @SuppressLint("ClickableViewAccessibility")
    private fun setupBackButton() {
        binding.btnBack.setOnTouchListener { view, event ->
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    binding.btnBack.setBackgroundResource(R.drawable.ic_back_pressed)
                    true
                }
                MotionEvent.ACTION_MOVE -> {
                    if (!isTouchInsideView(view, event)) {
                        binding.btnBack.setBackgroundResource(R.drawable.ic_back)
                    }
                    true
                }
                MotionEvent.ACTION_UP -> {
                    binding.btnBack.setBackgroundResource(R.drawable.ic_back)
                    if (isTouchInsideView(view, event)) {
                        backHome(this)
                    }
                    true
                }
                MotionEvent.ACTION_CANCEL -> {
                    binding.btnBack.setBackgroundResource(R.drawable.ic_back)
                    true
                }
                else -> false
            }
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    private fun setupSaveButton() {
        binding.btnSave.setOnTouchListener { view, event ->
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    binding.btnSave.setBackgroundResource(R.drawable.ic_save_pressed)
                    true
                }
                MotionEvent.ACTION_MOVE -> {
                    if (!isTouchInsideView(view, event)) {
                        binding.btnSave.setBackgroundResource(R.drawable.ic_save)
                    }
                    true
                }
                MotionEvent.ACTION_UP -> {
                    binding.btnSave.setBackgroundResource(R.drawable.ic_save)
                    if (isTouchInsideView(view, event)) {
                        if (saveExamInfo()) {
                            ToastManager.interruptedToast(this, "已保存", Toast.LENGTH_SHORT)
                            backHome(this)
                        }
                    }
                    true
                }
                MotionEvent.ACTION_CANCEL -> {
                    binding.btnSave.setBackgroundResource(R.drawable.ic_save)
                    true
                }
                else -> false
            }
        }
    }

    private fun setupTimeFormatSwitch() {
        binding.switchTimeFormat.isChecked = is24HourFormat
        updateTimeFormatText()
        binding.switchTimeFormat.setOnCheckedChangeListener { _, isChecked ->
            is24HourFormat = isChecked
            updateTimeFormatText()
            updateTimeDisplay()
        }
    }

    private fun setupDateButton() {
        updateDateDisplay()
        binding.btnDate.setOnClickListener {
            val currentCalendar = Calendar.getInstance() // 获取当前日期
            val minDate = currentCalendar.timeInMillis // 当前日期的毫秒时间戳
            DatePickerDialog(
                this,
                { _, year, month, day ->
                    // 用户选择的日期
                    val selectedCalendar = Calendar.getInstance().apply {
                        set(year, month, day)
                    }
                    // 检查选择的日期是否 >= 今天
                    if (selectedCalendar.timeInMillis >= minDate) {
                        selectedYear = year
                        selectedMonth = month
                        selectedDay = day
                        updateDateDisplay()
                    } else {
                        // 如果选择的是过去的日期，提示用户
                        ToastManager.interruptedToast(this, "不能选择过去的日期", Toast.LENGTH_SHORT)
                    }
                },
                selectedYear, selectedMonth, selectedDay
            ).apply {
                // 设置日期选择器的最小日期为今天
                datePicker.minDate = minDate
            }.show()
        }
    }

    private fun setupTimeButton() {
        updateTimeDisplay()
        binding.btnTime.setOnClickListener {
            val currentCalendar = Calendar.getInstance() // 获取当前时间
            val currentTimeInMillis = currentCalendar.timeInMillis // 当前时间的毫秒时间戳
            // 用户之前选择的日期（在 setupDateButton 中设置）
            val selectedDateCalendar = Calendar.getInstance().apply {
                set(selectedYear, selectedMonth, selectedDay)
            }

            TimePickerDialog(
                this,
                { _, hour, minute ->
                    // 用户选择的时间
                    val selectedDateTimeCalendar = Calendar.getInstance().apply {
                        set(selectedYear, selectedMonth, selectedDay, hour, minute)
                    }

                    // 检查选择的日期是否是今天
                    val isToday = selectedDateCalendar.get(Calendar.DAY_OF_YEAR) ==
                            currentCalendar.get(Calendar.DAY_OF_YEAR) &&
                            selectedDateCalendar.get(Calendar.YEAR) ==
                            currentCalendar.get(Calendar.YEAR)

                    if (!isToday || selectedDateTimeCalendar.timeInMillis >= currentTimeInMillis) {
                        // 如果不是今天，或者时间 >= 当前时间，允许选择
                        selectedHour = hour
                        selectedMinute = minute
                        updateTimeDisplay()
                    } else {
                        // 如果是今天且时间早于当前时间，提示用户
                        ToastManager.interruptedToast(this, "不能选择过去的时间", Toast.LENGTH_SHORT)
                    }
                },
                selectedHour,
                selectedMinute,
                is24HourFormat
            ).show()
        }
    }

    @SuppressLint("SetTextI18n")
    private fun setupDurationButton() {
        binding.btnDuration.setOnClickListener {
            ScrollingTimePickerDialog(this) { hour, minute ->
                duration = hour * 60 + minute
                updateDurationDisplay()
            }.apply {
                setDefaultTime(duration / 60, duration % 60)
            }.show()
        }
    }

    private fun setupAddReminderButton() {
        binding.btnAddReminder.setOnClickListener {
            if (remindOptions.all { option -> reminders.any { it.value == option.value } }) {
                ToastManager.interruptedToast(this, "已添加所有提醒选项", Toast.LENGTH_SHORT)
            } else {
                val dialog = AddRemindDialog(this, reminders)
                dialog.setOnConfirmListener(this)
                dialog.show()
            }
        }
    }

    private fun updateTimeFormatText() {
        binding.switchTimeFormat.text = getString(
            if (is24HourFormat) R.string.hint_time_format_24h
            else R.string.hint_time_format_12h
        )
        binding.tvStartTime.text = getString(
            if (is24HourFormat) R.string.hint_start_time_24h
            else R.string.hint_start_time_12h
        )
    }

    private fun updateDateDisplay() {
        binding.btnDate.text = getString(
            R.string.date_format,
            selectedMonth + 1,
            selectedDay
        )
    }

    private fun updateTimeDisplay() {
        binding.btnTime.text = if (is24HourFormat) {
            getString(R.string.time_24h_format, selectedHour, selectedMinute)
        } else {
            // 12小时制时段判断
            val (periodResId, displayHour) =
            when (selectedHour) {
                0 -> R.string.time_midnight to 12                                   // 半夜12:00
                in 1..5 -> R.string.time_midnight to selectedHour             // 半夜1:00-5:59
                in 6..8 -> R.string.time_morning to selectedHour             // 早上6:00-8:59
                in 9..11 -> R.string.time_forenoon to selectedHour            // 上午9:00-11:59
                12 -> R.string.time_afternoon to 12                                  // 下午12:00
                in 13..17 -> R.string.time_afternoon to selectedHour - 12      // 下午1:00-5:59
                in 18..23 -> R.string.time_evening to selectedHour - 12      // 晚上6:00-11:59
                else -> R.string.time_forenoon to selectedHour                      // 异常回退
            }
            getString(periodResId, displayHour, selectedMinute)
        }
    }

    @SuppressLint("SetTextI18n")
    private fun updateDurationDisplay() {
        binding.btnDuration.text = "${duration}分钟"
    }

    private fun updateRemindersDisplay() {
        val remindLayout = binding.fblRemind
        val addReminderButton = binding.btnAddReminder
        // 清空
        for (i in remindLayout.childCount - 1 downTo 0) {
            val child = remindLayout.getChildAt(i)
            if (child !== addReminderButton) {
                remindLayout.removeViewAt(i)
            }
        }
        // 添加
        reminders.forEach { reminder ->
            val title = secondsToString(reminder.value)
            val reminderView = LayoutInflater.from(this).inflate(
                R.layout.reminder_displayer, remindLayout, false
            )
            val remindTypeIcon = reminderView.findViewById<ImageView>(R.id.iv_remind_type)
            val remindTitle = reminderView.findViewById<TextView>(R.id.tv_remind_title)
            val cancelRemindButton = reminderView.findViewById<Button>(R.id.btn_cancel_remind)
            remindTypeIcon.setBackgroundResource(
                when (reminder.type) {
                    RemindType.NOTIFICATION -> R.drawable.ic_notification
                    RemindType.ALARM -> R.drawable.ic_alarm
                }
            )
            remindTitle.text = title
            cancelRemindButton.setOnClickListener {
                reminders.remove(reminder)
                updateRemindersDisplay()
            }
            remindLayout.addView(reminderView)
        }
    }

    private fun saveExamInfo(): Boolean {
        examName = binding.etExamName.text.toString()
        location = binding.etLocation.text.toString()
        startTime = createStartTime(selectedYear, selectedMonth + 1, selectedDay, selectedHour, selectedMinute)
        remark = binding.etRemark.text.toString()
        if (examName.isEmpty()) {
            ToastManager.interruptedToast(this, "考试名称不能为空", Toast.LENGTH_SHORT)
            return false
        }
        if (startTime == 0.toLong()) {
            ToastManager.interruptedToast(this, "请选择开始时间", Toast.LENGTH_SHORT)
            return false
        }
        if (duration <= 0) {
            ToastManager.interruptedToast(this, "请设置考试时长", Toast.LENGTH_SHORT)
            return false
        }
        if (dbHelper.checkTimeConflict(examName, startTime, duration)) {
            ToastManager.interruptedToast(this, "添加的考试和其它考试的时间有冲突", Toast.LENGTH_SHORT)
            return false
        }
        val result1 = dbHelper.insertExam(examName, location, startTime, duration, remark)
        val result2 = dbHelper.insertReminders(examName, startTime, reminders)
        if (!result1) {
            Log.e(TAG, "插入考试信息失败")
            return false
        } else if (!result2) {
            Log.e(TAG, "插入提醒序列失败")
            return false
        } else {
            Log.d(TAG, "考试信息插入成功，名称: $examName")
            return true
        }
    }

    @SuppressLint("DefaultLocale")
    private fun createStartTime(year: Int, month: Int, day: Int, hour: Int, minute: Int): Long {
        val startTimeString = String.format("%04d%02d%02d%02d%02d", year, month, day, hour, minute)
        return startTimeString.toLong()
    }

    private fun isTouchInsideView(view: View, event: MotionEvent): Boolean {
        val x = event.x
        val y = event.y
        return x >= 0 && x <= view.width && y >= 0 && y <= view.height
    }

    private fun secondsToString(seconds: Int): String {
        return RemindOptionProvider.findNameByValue(seconds)
    }
}